﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Subscriptions.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Represents an individual subscription declared by an object
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Engine.DynamicVariables
{
    using System.Collections.Generic;

    using Collaboris.Utils;

    /// <summary>
    /// Represents an individual subscription declared by an object
    /// </summary>
    public class VariableSubscription
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="VariableSubscription"/> class.
        /// </summary>
        /// <param name="objectName">
        /// Name of the object.
        /// </param>
        /// <param name="objectPropertyName">
        /// Name of the object property.
        /// </param>
        /// <param name="propertyExpression">
        /// The property expression.
        /// </param>
        /// <param name="instance">
        /// The instance.
        /// </param>
        public VariableSubscription(
            string objectName, string objectPropertyName, string propertyExpression, object instance)
        {
            this.ObjectName = objectName;
            this.ObjectPropertyName = objectPropertyName;
            this.PropertyExpression = propertyExpression;
            this.Instance = instance;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the instance.
        /// </summary>
        /// <value>The instance.</value>
        public object Instance { get; set; }

        /// <summary>
        /// Gets or sets the name of the object.
        /// </summary>
        /// <value>The name of the object.</value>
        public string ObjectName { get; set; }

        /// <summary>
        /// Gets or sets the name of the object property.
        /// </summary>
        /// <value>The name of the object property.</value>
        public string ObjectPropertyName { get; set; }

        /// <summary>
        /// Gets or sets the property expression.
        /// </summary>
        /// <value>The property expression.</value>
        public string PropertyExpression { get; set; }

        #endregion
    }

    /// <summary>
    /// Represents a collection of Variable Subscriptions
    /// </summary>
    public class VariableSubscriptions : List<VariableSubscription>
    {
    }

    /// <summary>
    /// Responsible for storing and managing all subscription created by all objects
    /// </summary>
    public class Subscriptions
    {
        #region Constants and Fields

        /// <summary>
        /// Stores the object subscriptions for each variable.
        /// </summary>
        private Dictionary<string, VariableSubscriptions> subscriptions =
            new Dictionary<string, VariableSubscriptions>();

        #endregion

        #region Properties

        /// <summary>
        /// Gets the variables.
        /// </summary>
        /// <value>The variables.</value>
        public IEnumerable<string> Variables
        {
            get
            {
                return this.subscriptions.Keys;
            }
        }

        #endregion

        #region Indexers

        /// <summary>
        /// Returns all subscriptions for a certain variable
        /// </summary>
        /// <param name="variableName">
        /// The variable name.
        /// </param>
        public VariableSubscriptions this[string variableName]
        {
            get
            {
                return this.subscriptions[variableName];
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Adds the object subscription.
        /// </summary>
        /// <param name="variableName">
        /// Name of the variable.
        /// </param>
        /// <param name="subscription">
        /// The subscription.
        /// </param>
        public void AddObjectSubscription(string variableName, VariableSubscription subscription)
        {
            ValidationHelper.VerifyStringArgument(variableName, "variableName");
            ValidationHelper.VerifyObjectArgument(subscription, "subscription");

            VariableSubscriptions variableSubscriptions;

            if (this.subscriptions.ContainsKey(variableName))
            {
                variableSubscriptions = this.subscriptions[variableName];
            }
            else
            {
                variableSubscriptions = new VariableSubscriptions();
                this.subscriptions.Add(variableName, variableSubscriptions);
            }

            variableSubscriptions.Add(subscription);
        }

        /// <summary>
        /// Clears the object instances.
        /// </summary>
        public void ClearObjectInstances()
        {
            foreach (VariableSubscriptions subcriptions in this.subscriptions.Values)
            {
                foreach (VariableSubscription subscription in subcriptions)
                {
                    subscription.Instance = null;
                }
            }
        }

        /// <summary>
        /// Registers the object instance.
        /// </summary>
        /// <param name="objectName">Name of the object.</param>
        /// <param name="instance">The object instance.</param>
        public void RegisterObjectInstance(string objectName, object instance)
        {
            foreach (VariableSubscriptions subcriptions in this.subscriptions.Values)
            {
                foreach (VariableSubscription subscription in subcriptions)
                {
                    if (subscription.ObjectName == objectName)
                    {
                        subscription.Instance = instance;
                    }
                }
            }
        }

        #endregion
    }
}